﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TheVerge.Base.Platform;

namespace TheVerge.Base.Models
{
    public class VMForums : AVM, IPinnable
    {
        public const string ACTIVE_FORUM_QS = "ActiveId";
        private int LoadFromPinId = -1;

        public event EventHandler ForumsLoaded = delegate { };

        public VMForum[] All
        {
            get { return GetValue(() => All); }
            set { SetValue(value, () => All); }
        }

        public VMForum Active
        {
            get { return GetValue(() => Active); }
            private set { SetValue(value, () => Active); }
        }

        public void Load()
        {
            if (All == null)
            {
                API.GetForums(result =>
                {
                    if (result != null)
                    {
                        All = result.All.Select(e => new VMForum(e)).ToArray();
                        if (LoadFromPinId > 0)
                        {
                            SetActiveForumFromPin();
                        }
                        ForumsLoaded(this, EventArgs.Empty);
                    }
                }, error => { });
            }
        }

        public void SetActiveForum(VMForum forum)
        {
            Active = forum;
        }

        public string DisplayName { get { return @"Forums"; } }

        public Uri Tile { get { return new Uri(@"/Images/Tiles/Forums.png", UriKind.Relative); } }

        public Dictionary<string, string> QueryStrings
        {
            get { return new Dictionary<string, string>(); }
        }

        public void LoadFromPin(Dictionary<string, string> queryStrings)
        {
            if (queryStrings.ContainsKey(ACTIVE_FORUM_QS))
            {
                try
                {
                    var id = int.Parse(queryStrings[ACTIVE_FORUM_QS]);
                    if (All == null || All.Length == 0)
                    {
                        var vm = new VMForum();
                        vm.LoadFromPin(queryStrings);
                        Active = vm;
                        ForumsLoaded(this, EventArgs.Empty);
                        return;
                    }
                    else
                    {
                        SetActiveForumFromPin();
                    }
                }
                catch { }
            }
        }

        private void SetActiveForumFromPin()
        {
            foreach (var f in All)
            {
                if (f.Id == LoadFromPinId)
                {
                    Active = f;
                    LoadFromPinId = -1;
                    return;
                }
            }
        }
    }

    public class VMForum : VMEntries, IPinnable
    {
        private ForumEntry BackingEntry;

        private const string ID_QS = @"Id";
        private const string NAME_QS = @"Name";
        private const string NEWPOSTCOUNT_QS = @"NewPostCount";
        private const string POSTCOUNT_QS = @"PostCount";
        private const string DESCRIPTION_QS = @"Description";
        private const string LOGOURL_QS = @"LogoUrl";
        private const string SELECTED_QS = @"Selected";

        public int Id { get { return BackingEntry.Id; } }
        public string Name { get { return BackingEntry.Name; } }
        public string PostsString { get { return string.Format(@"{0} Posts -{1} New", BackingEntry.PostCount, BackingEntry.NewPostCount); } }
        public string Description { get { return BackingEntry.Description; } }
        public string LogoUrl { get { return BackingEntry.LogoUrl; } }

        public VMForum(ForumEntry entry)
        {
            Initialize(entry);
        }

        public VMForum()
        {
            BackingEntry = new ForumEntry();
            Entries = new List<VMEntries<ArticleEntry>>();
        }

        public string DisplayName { get { return Name; } }

        public Uri Tile { get { return new Uri(LogoUrl, UriKind.Absolute); } }

        public Dictionary<string, string> QueryStrings
        {
            get
            {
                var dic = new Dictionary<string, string>();

                AddEntry(dic, VMForums.ACTIVE_FORUM_QS, Id);
                AddEntry(dic, ID_QS, Id);
                AddEntry(dic, NAME_QS, Name);
                AddEntry(dic, NEWPOSTCOUNT_QS, BackingEntry.NewPostCount);
                AddEntry(dic, POSTCOUNT_QS, BackingEntry.PostCount);
                AddEntry(dic, DESCRIPTION_QS, Description);
                AddEntry(dic, LOGOURL_QS, LogoUrl);
                if (SelectedEntries != null)
                    AddEntry(dic, SELECTED_QS, SelectedEntries.DisplayName);

                return dic;
            }
        }

        public void LoadFromPin(Dictionary<string, string> queryStrings)
        {
            try
            {
                var entry = new ForumEntry();
                entry.Description = GetEntry(queryStrings, DESCRIPTION_QS);
                entry.Id = int.Parse(GetEntry(queryStrings, ID_QS));
                entry.LogoUrl = GetEntry(queryStrings, LOGOURL_QS);
                entry.Name = GetEntry(queryStrings, NAME_QS);
                entry.NewPostCount = int.Parse(GetEntry(queryStrings, NEWPOSTCOUNT_QS));
                entry.PostCount = int.Parse(GetEntry(queryStrings, POSTCOUNT_QS));

                Initialize(entry);

                SelectEntryFromDisplayName(GetEntry(queryStrings, SELECTED_QS));
            }
            catch { }
        }

        private void Initialize(ForumEntry entry)
        {
            BackingEntry = entry;

            var active = new VMForumActive(BackingEntry.Id);
            var popular = new VMForumPopular(BackingEntry.Id);
            var recent = new VMForumRecent(BackingEntry.Id);

            Entries = new List<VMEntries<ArticleEntry>>(3);

            Entries.Add(active);
            Entries.Add(popular);
            Entries.Add(recent);

            SelectedEntries = active;
            SelectedEntries.Refresh();

            NotifyAll();
        }

        private static void AddEntry<T>(Dictionary<string, string> dic, string key, T val)
        {
            dic[key] = Factory.HttpUtility.UrlEncode(val.ToString());
        }

        private static string GetEntry(Dictionary<string, string> dic, string key)
        {
            return Factory.HttpUtility.UrlDecode(dic[key]);
        }
    }

    public abstract class VMForumEntries : VMEntries<ArticleEntry>
    {
        protected int ForumId;

        public VMForumEntries(int forumId)
        {
            ForumId = forumId;
        }
    }

    public class VMForumActive : VMForumEntries
    {
        public override string DisplayName { get { return @"Active"; } }

        public VMForumActive(int forumId) : base(forumId) { }

        protected override void LoadMoreImp(Action<APIResponse<ArticleEntry>> OnFinished, Action<Exception> OnError)
        {
            API.GetForumActive(LastPageLoaded + 1, ForumId, OnFinished, OnError);
        }
    }

    public class VMForumPopular : VMForumEntries
    {
        public override string DisplayName { get { return @"Popular"; } }

        public VMForumPopular(int forumId) : base(forumId) { }

        protected override void LoadMoreImp(Action<APIResponse<ArticleEntry>> OnFinished, Action<Exception> OnError)
        {
            API.GetForumPopular(LastPageLoaded + 1, ForumId, OnFinished, OnError);
        }
    }

    public class VMForumRecent : VMForumEntries
    {
        public override string DisplayName { get { return @"Recent"; } }

        public VMForumRecent(int forumId) : base(forumId) { }

        protected override void LoadMoreImp(Action<APIResponse<ArticleEntry>> OnFinished, Action<Exception> OnError)
        {
            API.GetForumRecent(LastPageLoaded + 1, ForumId, OnFinished, OnError);
        }
    }
}
